package com.boss.salary.service.impl;

import com.boss.common.entity.PageDTO;
import com.boss.common.util.DateUtils;
import com.boss.framework.dto.PaginationDTO;
import com.boss.framework.exception.AppRuntimeException;
import com.boss.salary.constant.SystemDictConstant;
import com.boss.salary.dao.IPayeeAcctDao;
import com.boss.salary.entity.PayeeAcct;
import com.boss.salary.service.IPayeeAcctService;
import com.boss.sys.utils.SysUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.boss.salary.parsingExcel.impl.ReadSalaryReportExcel.getCellValue;

/**
 * <br>Title:
 * <br>Description:
 * <br>Author:
 * <br>Date:
 */
@Service
public class PayeeAcctServiceImpl implements IPayeeAcctService {

    @Autowired
    private IPayeeAcctDao iPayeeAcctDao;


    @Override
    public PageDTO<PayeeAcct> getAccountInfo(PaginationDTO paginationDTO, Map<String, Object> queryParam) {
        List<PayeeAcct> list = iPayeeAcctDao.getAccountInfo(paginationDTO, queryParam);
        int total = iPayeeAcctDao.getAccountInfoTotal(queryParam);
        PageDTO<PayeeAcct> pageDTO = new PageDTO<>();
        pageDTO.setRows(list);
        pageDTO.setTotal(total);
        return pageDTO;
    }

    @Override
    public String checkRepeat(Map<String, Object> queryParams) {
        String message = "";
        PayeeAcct payeeAcct = new PayeeAcct();
        payeeAcct.setId(queryParams.get("id").toString());
        payeeAcct.setMofDivCode(queryParams.get("mofDivCode").toString());
        payeeAcct.setPayeeAcctCode(queryParams.get("payeeAcctCode").toString());
        int result = iPayeeAcctDao.checkRepeat(payeeAcct);
        if (result == 0) {
            payeeAcct.setPayeeAcctCode(null);
            payeeAcct.setPayeeAcctNo(queryParams.get("payeeAcctNo").toString());
            result = iPayeeAcctDao.checkRepeat(payeeAcct);
            if (result != 0) {
                message = "账户重复";
            }
        } else {
            message = "编码重复";
        }
        return message;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAccount(PayeeAcct payeeAcct) {
        payeeAcct.setId(SysUtils.generateGuid());
        payeeAcct.setCreateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        payeeAcct.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        payeeAcct.setIsDeleted(SystemDictConstant.IS_FALSE);
        iPayeeAcctDao.saveAccount(payeeAcct);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAccount(PayeeAcct payeeAcct) {
        payeeAcct.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
        iPayeeAcctDao.updateAccount(payeeAcct);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAccount(List<String> accountId) {
        for (String id: accountId) {
            PayeeAcct payeeAcct = new PayeeAcct();
            payeeAcct.setId(id);
            payeeAcct.setUpdateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
            payeeAcct.setIsDeleted(SystemDictConstant.IS_TRUE);
            iPayeeAcctDao.updateAccount(payeeAcct);
        }
    }

    @Override
    public List<String> getExccelColumnName() {
        List<String> list= new ArrayList<>();
        list.add("系统显示名");
        list.add("收款人姓名");
        list.add("收款人账户");
        list.add("收款人银行编码");
        list.add("收款人银行");
        return list;


    }

    @Override
    public void payeeAcctsExcel(OutputStream outputStream) throws IOException {
        //1,创建一个工作簿
        Workbook workbook = new HSSFWorkbook();
        //Workbook workbook = new XSSFWorkbook();
        //2,创建一个工作表
        Sheet sheet = workbook.createSheet("sheet1");
        //3，创建一行（1，1）
        Row row1 = sheet.createRow(0);
        //4，创建一个单元格
        Cell cell11 = row1.createCell(0);
        cell11.setCellValue("系统显示名");
        Cell cell12 = row1.createCell(1);
        cell12.setCellValue("收款人姓名");
        Cell cell13 = row1.createCell(2);
        cell13.setCellValue("收款人账户");
        Cell cell14 = row1.createCell(3);
        cell14.setCellValue("收款人银行编码");
        Cell cell15 = row1.createCell(4);
        cell15.setCellValue("收款人银行");
        workbook.write(outputStream);
        //关闭流
        outputStream.close();

        System.out.println("生成成功！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void Read(MultipartFile file, String province, String salaryMonth,List<String>payeeExccel) throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        List<String> slist= new ArrayList<>();
        //获取文件流
        BufferedInputStream fis = new BufferedInputStream(file.getInputStream());
        //获取文件名
        String fileName= file.getOriginalFilename();

        String substring = fileName.substring(fileName.lastIndexOf("."));
        //判断版本（07，03）
        Workbook workbook = ".xls".equals(substring) ? new HSSFWorkbook(fis) : new XSSFWorkbook(fis);
        try{
            readExcel(province,slist, fis, workbook, salaryMonth,payeeExccel);
        }catch (AppRuntimeException e){
            throw e;
        }
    }
    private void readExcel(String province, List<String> slist, BufferedInputStream fis, Workbook workbook, String salaryMonth,List<String>payeeExccel) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, IOException {
        List<PayeeAcct> payeeAcctsList = new ArrayList<>();
        Sheet sheet = workbook.getSheetAt(0);
        Calendar cal = Calendar.getInstance();
        Row rowTitle = sheet.getRow(0);
        if (rowTitle!=null) {
            //获取有效标题头
            int cellCount = rowTitle.getPhysicalNumberOfCells();
            for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                Cell cell = rowTitle.getCell(cellNum);
                if (cell != null) {
                   String cellValue = cell.getStringCellValue();
                    for (int i = 0; i < payeeExccel.size(); i++) {
                        if(payeeExccel.get(i).equals(cellValue)){
                            slist.add(payeeExccel.get(i));
                        }
                    }
                }
            }
            if(slist.size()!=cellCount){
                throw new AppRuntimeException("存在无法读取的工资项");
            }
        }
        // 获取表中的内容
        int rowCount = sheet.getPhysicalNumberOfRows();
        for (int rowNum = 1; rowNum < rowCount ; rowNum++) {
            Row rowData = sheet.getRow(rowNum);
            PayeeAcct payeeAccts = new PayeeAcct();
            if (rowData!=null){
                // 读取列
                int cellCount = rowTitle.getPhysicalNumberOfCells();
                for (int cellNum = 0; cellNum < cellCount ; cellNum++) {
                    if(cellNum==0){
                        Cell cell = rowData.getCell(cellNum);
                        String showName=getCellValue(cell).toString();
                        payeeAccts.setShowName(showName);
                    }
                    if(cellNum==1){
                        Cell cell = rowData.getCell(cellNum);
                        String payeeAcctName=getCellValue(cell).toString();
                        payeeAccts.setPayeeAcctName(payeeAcctName);
                    }
                    if(cellNum==2){
                        Cell cell = rowData.getCell(cellNum);
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        String payeeAcctNo=getCellValue(cell).toString();
                        payeeAccts.setPayeeAcctNo(payeeAcctNo);
                    }
                    if(cellNum==3){
                        Cell cell = rowData.getCell(cellNum);
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        String payeeAcctCode=getCellValue(cell).toString();
                        payeeAccts.setPayeeAcctCode(payeeAcctCode);
                    }
                    if(cellNum==4){
                        Cell cell = rowData.getCell(cellNum);
                        String payeeAcctBankName=getCellValue(cell).toString();
                        payeeAccts.setPayeeAcctBankName(payeeAcctBankName);
                    }
                }
                //获取当前插入所需要的数学值
                payeeAccts.setId(SysUtils.generateGuid());
                payeeAccts.setCreateTime(String.valueOf(DateUtils.getCurrentTimeStamp()));
                payeeAccts.setYear(String.valueOf(cal.get(Calendar.YEAR)));
                payeeAccts.setIsDeleted(0);
                payeeAccts.setMofDivCode(province);
                payeeAcctsList.add(payeeAccts);
            }
        }
        //调用对比看当前的exl中内容是否有相同
        List<String>payeeAcctNoList=getDuplicateElement(payeeAcctsList,false);
        List<String>payeeAcctCodeList=getDuplicateElements(payeeAcctsList,false);
        PayeeAcct payeeAcct=new PayeeAcct();

        if(payeeAcctNoList.size()>0){
//            for(String acctNo :payeeAcctNoList){
//                payeeAcct.setPayeeAcctNo(acctNo);
//                throw new AppRuntimeException("收款人账号:"+payeeAcct.getPayeeAcctNo()+"重复");
//            }
            throw new AppRuntimeException("收款人账号:"+payeeAcctNoList.toString()+"重复");
        }
        if(payeeAcctCodeList.size()>0){
//            for(String acctCode :payeeAcctNoList){
//                payeeAcct.setPayeeAcctCode(acctCode);
//                throw new AppRuntimeException("收款人账号:"+payeeAcct.getPayeeAcctCode()+"重复");
//            }
            throw new AppRuntimeException("收款人银行编码:"+payeeAcctCodeList.toString()+"重复");
        }
        // 查询数据库数据看和传过来的数据是否有重复
        List<PayeeAcct> list = iPayeeAcctDao.getAccountInfoList(province);
        for(PayeeAcct payeeAccts:payeeAcctsList){
            for(PayeeAcct payeeAccts1:list){
                if(payeeAccts.getPayeeAcctCode().equals(payeeAccts1.getPayeeAcctCode())){
                    throw new AppRuntimeException("收款人银行编码:"+payeeAccts.getPayeeAcctCode()+"重复");
                }
                if(payeeAccts.getPayeeAcctNo().equals(payeeAccts1.getPayeeAcctNo())){
                    throw new AppRuntimeException("收款人账户:"+payeeAccts.getPayeeAcctNo()+"重复");
                }
            }
        }
        iPayeeAcctDao.insertPayeeAcctList(payeeAcctsList);
        fis.close();

    }
    //比对方法查收款人银行编码
    public static List<String> getDuplicateElements(List<PayeeAcct>list, boolean flag){
        return list.stream().map(e->{return flag? e.getPayeeAcctCode():e.getPayeeAcctCode();}).collect(Collectors.toMap(e->e,e->1,Integer::sum))
                .entrySet().stream().filter(entry->entry.getValue()>1).map(Map.Entry::getKey).collect(Collectors.toList());
    }
    //比对方法查收款人账号
    public static List<String> getDuplicateElement(List<PayeeAcct>list, boolean flag){
        return list.stream().map(e->{return flag? e.getPayeeAcctNo():e.getPayeeAcctNo();}).collect(Collectors.toMap(e->e,e->1,Integer::sum))
                .entrySet().stream().filter(entry->entry.getValue()>1).map(Map.Entry::getKey).collect(Collectors.toList());
    }
}
